package br.com.Orange.negocio;

import java.util.Collection;

import br.com.Orange.dao.cliente.RepositorioCliente;
import br.com.Orange.dao.FabricaRepositorio;
import br.com.Orange.dao.funcionarios.RepositorioFuncionario;
import br.com.Orange.dao.permanencia.RepositorioPermanencia;
import br.com.Orange.dao.produto.RepositorioProduto;
import br.com.Orange.dao.quarto.RepositorioQuarto;
import br.com.Orange.negocio.cliente.CadastroClientes;
import br.com.Orange.negocio.cliente.exception.ClienteExistenteException;
import br.com.Orange.negocio.cliente.exception.ClienteInexistenteException;
import br.com.Orange.negocio.cliente.model.Cliente;
import br.com.Orange.negocio.funcionario.CadastroFuncionarios;
import br.com.Orange.negocio.funcionario.exception.FuncionarioExistenteException;
import br.com.Orange.negocio.funcionario.exception.FuncionarioInexistenteException;
import br.com.Orange.negocio.funcionario.model.Funcionario;
import br.com.Orange.negocio.permanencia.CadastroPermanencia;
import br.com.Orange.negocio.permanencia.exception.ConsumoInexistenteException;
import br.com.Orange.negocio.permanencia.exception.PermanenciaInexistenteException;
import br.com.Orange.negocio.permanencia.exception.PermanenciaJaFechadaException;
import br.com.Orange.negocio.permanencia.model.Permanencia;
import br.com.Orange.negocio.produto.CadastroProdutos;
import br.com.Orange.negocio.produto.exception.ProdutoExistenteException;
import br.com.Orange.negocio.produto.exception.ProdutoIndisponivelException;
import br.com.Orange.negocio.produto.exception.ProdutoInexistenteException;
import br.com.Orange.negocio.produto.model.Produto;
import br.com.Orange.negocio.quarto.CadastroQuartos;
import br.com.Orange.negocio.quarto.CadastroTipoQuarto;
import br.com.Orange.negocio.quarto.exception.QuartoExistenteException;
import br.com.Orange.negocio.quarto.exception.QuartoIndisponivelException;
import br.com.Orange.negocio.quarto.exception.QuartoInexistenteException;
import br.com.Orange.negocio.quarto.exception.TipoQuartoExistenteException;
import br.com.Orange.negocio.quarto.exception.TipoQuartoInexistenteException;
import br.com.Orange.negocio.quarto.model.Quarto;
import br.com.Orange.negocio.quarto.model.TipoQuarto;
import br.com.Orange.util.dados.exception.RepositorioVazioException;

public class Fachada {
	
	private static Fachada instancia;
	private CadastroClientes clientes;
	private CadastroFuncionarios funcionarios;
	private CadastroPermanencia permanencias;
	private CadastroProdutos produtos;
	private CadastroQuartos quartos;
	private CadastroTipoQuarto tipos;
	
	private Fachada(){
		this.initCadastro();
	}
	
	private void initCadastro(){
		
		FabricaRepositorio fabrica = FabricaRepositorio.obterFabrica();
		
		RepositorioCliente repClientes = fabrica.criarRepositorioClientes();
		clientes = new CadastroClientes(repClientes);
		RepositorioFuncionario repFuncionarios = fabrica.criarRepositorioFuncionarios();
		funcionarios = new CadastroFuncionarios(repFuncionarios);
		RepositorioPermanencia repPermanencias = fabrica.criarRepositorioPermanencia();
		permanencias = new CadastroPermanencia(repPermanencias);
		RepositorioProduto repProdutos = fabrica.criarRepositorioProdutos();
		produtos = new CadastroProdutos(repProdutos);
		RepositorioQuarto repQuartos = fabrica.criarRepositorioQuartos();
		quartos = new CadastroQuartos(repQuartos);
		
//		RepositorioTipoQuarto repTipos = fabrica;
//		tipos = new CadastroTipoQuarto(repTipos);
	}
	
	public static Fachada obterInstancia(){
		if (instancia==null){
			instancia = new Fachada();
		}
		return instancia;
	}
	
	public void inserirCliente(Cliente cliente) throws ClienteExistenteException{
		clientes.inserir(cliente);
	}
	
	public Cliente procurarCliente(String CPF) throws ClienteInexistenteException{
		return clientes.procurar(CPF);
	}
		
	public void atualizarCliente(Cliente cliente) throws ClienteInexistenteException{
		clientes.atualizar(cliente);
	}
	
	public void removerCliente(String CPF) throws ClienteInexistenteException{
		clientes.remover(CPF);
	}

	public Collection<Cliente> listarClientes() throws RepositorioVazioException{
		return clientes.listar();
	}
	
	public boolean existeCliente(String CPF){
		return clientes.existe(CPF);
	}
	
	
	
	
	public void inserirFuncionario(String nome, String CPF, double salario, String senha) 
						throws FuncionarioExistenteException{
		funcionarios.inserirFuncionario(nome, CPF, salario, senha);
	}
	
	public void inserirGerente(String nome, String CPF, double salario, String senha) 
						throws FuncionarioExistenteException{
		funcionarios.inserirGerente(nome, CPF, salario, senha);
	}
	
	public Funcionario procurarFuncionario (int matricula) 
						throws FuncionarioInexistenteException{
		return funcionarios.procurar(matricula);
	}
	
	public void atualizarFuncionario(Funcionario funcionario) 
						throws FuncionarioInexistenteException{
		funcionarios.atualizar(funcionario);
	}
	
	public void removerFuncionario(int matricula) throws FuncionarioInexistenteException{
		funcionarios.remover(matricula);
	}
	
	public Collection<Funcionario> listarFuncionarios() throws RepositorioVazioException{
		return funcionarios.listar();
	}
	
	public boolean existeFuncionario(int matricula){
		return funcionarios.existe(matricula);
	}
	
	
	
	public void inserirProduto(String nome, double preco, int quantidade)
									throws ProdutoExistenteException{
		produtos.inserir(nome, preco, quantidade);
	}
	
	
	public Produto procurarProduto(int codigo) throws ProdutoInexistenteException{
		return produtos.procurar(codigo);
	}
	
	
	public void atualizarProduto(Produto produto) throws ProdutoInexistenteException{
		produtos.atualizar(produto);		
	}
	
	public void removerProduto(int codigo) throws ProdutoInexistenteException{
		produtos.remover(codigo);
	}
	
	
	public void listarProdutos() throws RepositorioVazioException{
		produtos.listar();
	}
	
	public void venderProduto(Produto produto, int quantidade) 
							throws ProdutoIndisponivelException, ProdutoInexistenteException{
		produtos.vender(produto, quantidade);
	}
	
	public void abastecerProduto(Produto produto, int quantidade) 
											throws ProdutoInexistenteException{
		produtos.abastecer(produto, quantidade);
	}
	
	
	
	
	public void inserirQuarto(Quarto quarto)
									throws QuartoExistenteException{
		quartos.inserir(quarto);
	}

	public Quarto procurarQuarto(int numero) throws QuartoInexistenteException{
		return quartos.procurar(numero);
	}

	public void removerQuarto(int numero) throws QuartoInexistenteException, 
									QuartoIndisponivelException{
		if	(quartos.isDisponivel(numero)){
			quartos.remover(numero);
		}
	}

	public void atualizarQuarto(Quarto quarto) throws QuartoInexistenteException, 
									QuartoIndisponivelException{
		if (quartos.isDisponivel(quarto.getNumero())){
			quartos.atualizar(quarto);
		}
	}

	public void listarQuartosDisponiveis() throws RepositorioVazioException{
		quartos.listarDisponiveis();
	}
	
	public void listarQuartos() throws RepositorioVazioException{
		quartos.listar();
	}

		
	
	
	public void inserirPermanencia(int matricula, int numeroQuarto)
						throws QuartoInexistenteException, QuartoIndisponivelException, 
						FuncionarioInexistenteException{
		quartos.isDisponivel(numeroQuarto);
		Quarto quarto = (Quarto) quartos.procurar(numeroQuarto).clone();	
		Funcionario funcionario = (Funcionario) funcionarios.procurar(matricula).clone();
		permanencias.inserir(funcionario, quarto);
		Quarto quartoAtualizado = new Quarto(quarto.getNumero(), quarto.getTipo(), false);
		quartos.atualizar(quartoAtualizado);
	}
	
	public Permanencia procurarPermanencia(int codigo) throws PermanenciaInexistenteException{
		return permanencias.procurar(codigo);
	}
	
	public void fecharPermanencia(int codigo, String CPFCliente) 
			throws PermanenciaInexistenteException, ClienteInexistenteException,
					PermanenciaJaFechadaException, 
					QuartoInexistenteException, QuartoIndisponivelException{
		Permanencia permanencia = permanencias.procurar(codigo);
		if (!CPFCliente.equalsIgnoreCase("0")){
			Cliente cliente = (Cliente) clientes.procurar(CPFCliente).clone();
			permanencias.fechar(permanencia, cliente);
		}else{
			permanencias.fechar(permanencia);
		}
//		permanencias.imprimirConsumo(permanencia);
		Quarto quarto = permanencia.getQuarto();
		Quarto quartoAtualizado = new Quarto(quarto.getNumero(), quarto.getTipo());
		quartos.atualizar(quartoAtualizado);
		
	}
	
	public void adicionarProdutoPermanencia(
							Permanencia permanencia, int codigoProduto, int quantidade) 
					throws PermanenciaInexistenteException, ProdutoInexistenteException, 
						   ProdutoIndisponivelException, PermanenciaJaFechadaException{
		Produto produto = (Produto) produtos.procurar(codigoProduto).clone();
		produtos.vender(produto, quantidade);
		permanencias.adicionarConsumo(permanencia, produto, quantidade);
		
	}
	
	public void removerProdutoPermanencia(Permanencia permanencia, int codProduto) 
				throws PermanenciaInexistenteException, ProdutoInexistenteException, 
					   ConsumoInexistenteException, PermanenciaJaFechadaException{
		Produto produto = produtos.procurar(codProduto);
		permanencias.removerConsumo(permanencia, produto);
		produtos.abastecer(produto, 1);
	}
	
	
	public void listarPermanencias() throws RepositorioVazioException{
		permanencias.listar();
	}
	
	public void listarPermanenciasFuncionario(int matricula) 
					throws RepositorioVazioException, FuncionarioInexistenteException{
		Funcionario funcionario = funcionarios.procurar(matricula);
		if (funcionario != null){
			permanencias.listarPermanenciasFuncionario(matricula);
		}else{
			throw new FuncionarioInexistenteException(matricula);
		}
	}
	
	public void listarPermanenciasCliente(String CPF) 
			throws RepositorioVazioException, ClienteInexistenteException{
		Cliente cli = clientes.procurar(CPF);
		if (cli != null){
			permanencias.listarPermanenciasCliente(cli);
		}else{
			throw new ClienteInexistenteException(CPF);
		}
		
	}
	
	public void listarPermanenciasAbertas() throws RepositorioVazioException{
		permanencias.listarAbertas();
	}
	
	public void listarPermanenciasFechadas() throws RepositorioVazioException{
		permanencias.listarFechadas();
	}

	
	
	
	public void inserirTipo(TipoQuarto tipo) throws TipoQuartoExistenteException{
		tipos.inserir(tipo);
	}
	
	public void atualizarTipo(TipoQuarto tipo) throws TipoQuartoInexistenteException{
		tipos.atualizar(tipo);
	}
	
	public TipoQuarto procurarTipo(int codigo) throws TipoQuartoInexistenteException{
		return tipos.procurar(codigo);
	}
	
	public void removerTipo(int codigo) throws TipoQuartoInexistenteException{
		tipos.remover(codigo);
	}
	
	public void listarTipos() throws RepositorioVazioException{
		tipos.listar();
	}
	
}
